<template>
    <div class="pdf-recognition-page">
      <!-- 顶部导航栏 -->
      <nav-bar :is-loggedin="false" :theme-icon="'fas fa-moon'" @toggle-theme="toggleTheme" @login="handleLogin" />
  
      <div class="page-container">
        <!-- 主内容区域：左右分栏布局 -->
        <div class="main-content">
          <!-- 左侧：文件列表区域 -->
          <div class="left-panel">
            <!-- 页面标题 -->
            <div class="page-header">
              <h1 class="page-title">
                <i class="el-icon-document"></i>
                PDF文件转换
              </h1>
              <p class="page-subtitle">批量上传PDF文件，自动识别并转换为word文档</p>
            </div>
            
            <!-- 按钮区域 -->
            <div class="action-buttons">
              <el-button 
                type="default" 
                icon="el-icon-plus"
                @click="triggerFileSelect"
              >
                选择文件
              </el-button>
              <el-button 
                type="primary" 
                icon="el-icon-upload2"
                :loading="uploading || recognizing" 
                :disabled="fileList.length === 0 || uploading || recognizing"
                @click="handleBatchUpload"
              >
                全部上传并转换
              </el-button>
              <!-- 隐藏的文件选择input -->
              <input 
                ref="fileInput"
                type="file"
                accept=".pdf"
                multiple
                style="display: none"
                @change="handleFileSelect"
              />
            </div>
            
            <!-- 选项 -->
            <div class="upload-options">
              <el-checkbox v-model="autoRecognizeAfterUpload">
                上传后自动转换
              </el-checkbox>
            </div>
            
            <!-- 统计信息 -->
            <div class="section-stats">
              <span class="stat-item">
                <i class="el-icon-upload"></i>
                已上传: {{ uploadedFiles.length }}
              </span>
              <span class="stat-item">
                <i class="el-icon-loading"></i>
                转换中: {{ recognizingFiles.length }}
              </span>
              <span class="stat-item">
                <i class="el-icon-success"></i>
                已完成: {{ recognizedFiles.length }}
              </span>
            </div>
  
            <!-- 文件列表 -->
            <div class="files-list">
              <div 
                v-for="(file, index) in fileList" 
                :key="file.uid || index"
                class="file-item"
                :class="{ 
                  'uploaded': file.status === 'uploaded',
                  'recognizing': file.status === 'recognizing',
                  'recognized': file.status === 'recognized',
                  'error': file.status === 'error',
                  'active': selectedFileIndex === index
                }"
                @click="selectFile(index)"
              >
                <div class="file-icon">
                  <i class="el-icon-document" v-if="file.status === 'ready'"></i>
                  <i class="el-icon-upload" v-else-if="file.status === 'uploading'"></i>
                  <i class="el-icon-success" v-else-if="file.status === 'uploaded'"></i>
                  <i class="el-icon-loading" v-else-if="file.status === 'recognizing'"></i>
                  <i class="el-icon-check" v-else-if="file.status === 'recognized'"></i>
                  <i class="el-icon-error" v-else-if="file.status === 'error'"></i>
                </div>
                <div class="file-info">
                  <div class="file-name" :title="file.name">{{ file.name }}</div>
                  <div class="file-meta">
                    <span class="file-size">{{ formatFileSize(file.size) }}</span>
                    <span class="file-status" :class="file.status">
                      {{ getStatusText(file.status) }}
                    </span>
                  </div>
                  <div class="file-progress" v-if="file.status === 'uploading' || file.status === 'recognizing'">
                    <el-progress 
                      :percentage="file.progress || 0" 
                      :status="file.status === 'error' ? 'exception' : ''"
                      :stroke-width="4"
                    ></el-progress>
                  </div>
                  <div class="file-error" v-if="file.status === 'error' && file.errorMessage">
                    <i class="el-icon-warning"></i>
                    {{ file.errorMessage }}
                  </div>
                </div>
                <div class="file-actions">
                  <el-button 
                    v-if="file.status === 'uploaded' && file.status !== 'recognizing' && file.status !== 'recognized'"
                    type="text" 
                    size="small"
                    @click.stop="recognizeFile(index)"
                  >
                    <i class="el-icon-refresh"></i>
                  </el-button>
                  <el-button 
                    type="text" 
                    size="small"
                    @click.stop="removeFile(index)"
                  >
                    <i class="el-icon-delete"></i>
                  </el-button>
                </div>
              </div>
  
              <div v-if="fileList.length === 0" class="empty-state">
                <i class="el-icon-document"></i>
                <p>点击"选择文件"按钮添加PDF文件</p>
              </div>
            </div>
          </div>
  
          <!-- 右侧：文件对比区域 -->
          <div class="right-panel">
            <div v-if="selectedFile && selectedFileIndex >= 0" class="comparison-section">
              <div class="section-header">
                <h2 class="section-title">
                  <i class="el-icon-view"></i>
                  文件对比: {{ selectedFile.name }}
                </h2>
                <el-button type="text" @click="closeComparison">
                  <i class="el-icon-close"></i>
                  关闭
                </el-button>
              </div>

              <div class="comparison-container">
                <!-- 原文件预览 -->
                <div class="comparison-panel original-panel">
                  <div class="panel-header">
                    <i class="el-icon-document"></i>
                    <span>原文件</span>
                    <el-button 
                      v-if="selectedFile.originalUrl" 
                      type="text" 
                      size="small"
                      @click="downloadOriginalFile"
                    >
                      <i class="el-icon-download"></i>
                      下载
                    </el-button>
                  </div>
                  <div class="panel-content">
                    <iframe 
                      v-if="selectedFile.originalUrl"
                      :src="selectedFile.originalUrl + '#toolbar=1&navpanes=1&scrollbar=1'" 
                      class="pdf-viewer"
                      frameborder="0"
                      type="application/pdf"
                    ></iframe>
                    <div v-else-if="selectedFile.raw" class="no-preview">
                      <i class="el-icon-loading"></i>
                      <p>正在加载预览...</p>
                    </div>
                    <div v-else class="no-preview">
                      <i class="el-icon-picture-outline"></i>
                      <p>无法预览原文件</p>
                    </div>
                  </div>
                </div>

                <!-- 转换结果 -->
                <div class="comparison-panel recognized-panel">
                  <div class="panel-header">
                    <i class="el-icon-edit-outline"></i>
                    <span>转换结果</span>
                    <div class="panel-actions">
                      <el-button 
                        v-if="selectedFile.downloadUrl" 
                        type="text" 
                        size="small"
                        @click="downloadRecognizedFile"
                      >
                        <i class="el-icon-download"></i>
                        另存为docx
                      </el-button>
                      <el-button 
                        v-if="selectedFile.recognizedContent" 
                        type="text" 
                        size="small"
                        @click="copyRecognizedContent"
                      >
                        <i class="el-icon-document-copy"></i>
                        复制
                      </el-button>
                    </div>
                  </div>
                  <div class="panel-content">
                    <div class="recognized-content" v-if="selectedFile.recognizedContent">
                      <VueMarkdown class="recognized-text" :source="selectedFile.recognizedContent" />
                    </div>
                    <div v-else-if="selectedFile.status === 'recognizing'" class="no-content">
                      <i class="el-icon-loading"></i>
                      <p>转换中，请稍候...</p>
                      <el-progress 
                        :percentage="selectedFile.progress || 0" 
                        :status="''"
                        :stroke-width="6"
                      ></el-progress>
                    </div>
                    <div v-else-if="selectedFile.status === 'uploaded'" class="no-content">
                      <i class="el-icon-warning"></i>
                      <p>文件已上传，但尚未转换</p>
                      <el-button 
                        type="primary" 
                        size="small"
                        @click="recognizeFile(selectedFileIndex)"
                      >
                        <i class="el-icon-refresh"></i>
                        开始转换
                      </el-button>
                    </div>
                    <div v-else class="no-content">
                      <i class="el-icon-picture-outline"></i>
                      <p>暂无转换结果</p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div v-else class="no-selection">
              <i class="el-icon-document"></i>
              <p>请从左侧文件列表中选择一个文件查看对比</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </template>
  
  <script>
  import { runWorkflow } from '@/api/dify/workflow'
  import { getToken } from '@/utils/auth'
  import request from '@/utils/request'
  import NavBar from '@/layout/UserView/NavBar.vue'
  import VueMarkdown from 'vue-markdown'
  
  export default {
    name: 'PDFRecognition',
    components: {
      NavBar,
      VueMarkdown
    },
    data() {
      return {
        fileList: [], // 文件列表
        selectedFileIndex: -1, // 当前选中的文件索引
        uploading: false, // 是否正在上传
        recognizing: false, // 是否正在转换
        autoRecognizeAfterUpload: true, // 上传后自动转换
        uploadAction: '', // 上传地址（不使用，手动上传）
        uploadHeaders: {
          token: getToken() || ''
        },
        uploadData: {
          userId: this.getUserId(),
          appName: this.$route.query.appName || null
        },
        // 工作流配置
        workflowConfig: {
          variableName: 'files', // 工作流输入变量名
          responseMode: 'streaming' // 响应模式
        }
      }
    },
    computed: {
      // 已上传的文件
      uploadedFiles() {
        return this.fileList.filter(f => f.status === 'uploaded' || f.status === 'recognizing' || f.status === 'recognized')
      },
      // 正在转换的文件
      recognizingFiles() {
        return this.fileList.filter(f => f.status === 'recognizing')
      },
      // 已完成转换的文件
      recognizedFiles() {
        return this.fileList.filter(f => f.status === 'recognized')
      },
      // 当前选中的文件
      selectedFile() {
        if (this.selectedFileIndex >= 0 && this.selectedFileIndex < this.fileList.length) {
          return this.fileList[this.selectedFileIndex]
        }
        return null
      }
    },
    methods: {
      // 获取用户ID
      getUserId() {
        // 从localStorage或token中获取用户ID
        const token = getToken()
        if (token) {
          try {
            const payload = JSON.parse(atob(token.split('.')[1]))
            return payload.userId || payload.sub || 'default-user'
          } catch (e) {
            return 'default-user'
          }
        }
        return 'default-user'
      },
  
      // 触发文件选择
      triggerFileSelect() {
        this.$refs.fileInput.click()
      },
      
      // 处理文件选择
      handleFileSelect(event) {
        const files = Array.from(event.target.files || [])
        if (files.length === 0) return
        
        // 只保留PDF文件
        const pdfFiles = files.filter(f => {
          const isPdf = f.name.toLowerCase().endsWith('.pdf')
          if (!isPdf) {
            this.$message.warning(`文件 ${f.name} 不是PDF格式，已自动忽略`)
          }
          return isPdf
        })
        
        // 添加到文件列表
        pdfFiles.forEach(file => {
          const fileObj = {
            uid: Date.now() + Math.random(),
            name: file.name,
            size: file.size,
            raw: file,
            status: 'ready', // ready, uploading, uploaded, recognizing, recognized, error
            progress: 0,
            uploadFileId: null, // Dify返回的文件ID
            recognizedContent: null, // 转换结果（markdown格式）
            originalUrl: null, // 原文件预览URL
            downloadUrl: null, // 转换结果文件下载URL
            downloadFileName: null, // 转换结果文件下载文件名
            errorMessage: null
          }
          this.fileList.push(fileObj)
        })
        
        // 清空input，允许重复选择同一文件
        if (this.$refs.fileInput) {
          this.$refs.fileInput.value = ''
        }
        
        if (pdfFiles.length > 0) {
          this.$message.success(`已添加 ${pdfFiles.length} 个PDF文件`)
        }
      },
      
      // 文件选择变化（保留用于兼容）
      handleFileChange(file, fileList) {
        // 这个方法现在不再使用，但保留以防其他地方调用
        this.handleFileSelect({ target: { files: [file.raw] } })
      },
  
      // 移除文件
      handleFileRemove(file, fileList) {
        this.fileList = fileList
        if (this.selectedFileIndex >= this.fileList.length) {
          this.selectedFileIndex = -1
        }
      },
  
      // 删除文件
      removeFile(index) {
        this.fileList.splice(index, 1)
        if (this.selectedFileIndex >= this.fileList.length) {
          this.selectedFileIndex = -1
        }
      },
  
      // 批量上传文件并自动转换
      async handleBatchUpload() {
        const filesToUpload = this.fileList.filter(f => f.status === 'ready')
        if (filesToUpload.length === 0) {
          this.$message.warning('没有可上传的文件')
          return
        }

        this.uploading = true
        const uploadPromises = filesToUpload.map((file, index) => this.uploadSingleFile(file, index))
        
        try {
          await Promise.all(uploadPromises)
          this.$message.success(`成功上传 ${filesToUpload.length} 个文件`)
          
          // 上传完成后自动转换
          // 等待一小段时间确保上传状态更新完成
          await new Promise(resolve => setTimeout(resolve, 500))
          // 自动转换已上传的文件
          const uploadedFiles = this.fileList.filter(f => f.status === 'uploaded' && f.uploadFileId)
          if (uploadedFiles.length > 0) {
            this.$message.info(`开始自动转换 ${uploadedFiles.length} 个文件...`)
            await this.handleBatchRecognize()
          }
        } catch (error) {
          this.$message.error('部分文件上传失败，请查看文件状态')
        } finally {
          this.uploading = false
        }
      },
  
      // 上传单个文件
      async uploadSingleFile(file, index) {
        const fileIndex = this.fileList.findIndex(f => f.uid === file.uid)
        if (fileIndex === -1) return
  
        this.$set(this.fileList[fileIndex], 'status', 'uploading')
        this.$set(this.fileList[fileIndex], 'progress', 0)
  
        try {
          const formData = new FormData()
          formData.append('file', file.raw)
          formData.append('userId', this.uploadData.userId)
          if (this.uploadData.appName) {
            formData.append('appName', this.uploadData.appName)
          }
  
          // 模拟上传进度
          const progressInterval = setInterval(() => {
            if (this.fileList[fileIndex].progress < 90) {
              this.$set(this.fileList[fileIndex], 'progress', this.fileList[fileIndex].progress + 10)
            }
          }, 200)
  
          // 使用 /dev-api/api/ai/chat/upload 接口上传文件
          // request 的 baseURL 是 /dev-api，所以实际请求路径是 /dev-api/api/ai/chat/upload
          const response = await request({
            url: '/api/ai/chat/upload',
            method: 'post',
            data: formData,
            timeout: 60000 // 文件上传需要更长的超时时间
          })
          
          clearInterval(progressInterval)
          this.$set(this.fileList[fileIndex], 'progress', 100)
  
          if (response && response.code === 200 && response.data) {
            const fileData = response.data
            // 从上传文件的响应中提取 upload_file_id
            let uploadFileId = null
            
            // 优先使用后端直接返回的 uploadFileId 字段（后端已设置）
            if (fileData.uploadFileId) {
              uploadFileId = fileData.uploadFileId
              console.log('从 uploadFileId 字段获取到文件ID:', uploadFileId)
            }
            // 其次从 difyResponse 中解析（后端会将 upload_file_id 放在这里）
            else if (fileData.difyResponse) {
              try {
                const difyResp = typeof fileData.difyResponse === 'string' 
                  ? JSON.parse(fileData.difyResponse) 
                  : fileData.difyResponse
                // 优先使用 upload_file_id，然后是 id，最后是 file_id
                uploadFileId = difyResp.upload_file_id || difyResp.id || difyResp.file_id
                console.log('从 difyResponse 中提取到 upload_file_id:', uploadFileId)
              } catch (e) {
                console.error('解析Dify响应失败', e)
              }
            }
            // 最后尝试直接从 fileData 中获取其他可能的字段
            else {
              uploadFileId = fileData.upload_file_id || fileData.id
            }
            
            if (!uploadFileId) {
              console.error('无法从响应中提取 upload_file_id，响应数据:', fileData)
              throw new Error('无法获取文件ID，上传响应格式不正确')
            }
            
            console.log('最终获取到的 upload_file_id:', uploadFileId)
  
            this.$set(this.fileList[fileIndex], 'status', 'uploaded')
            this.$set(this.fileList[fileIndex], 'uploadFileId', uploadFileId)
            // 保存原始文件的预览URL
            if (file.raw) {
              const objectUrl = URL.createObjectURL(file.raw)
              this.$set(this.fileList[fileIndex], 'originalUrl', objectUrl)
            } else if (file.url) {
              this.$set(this.fileList[fileIndex], 'originalUrl', file.url)
            }
            this.$set(this.fileList[fileIndex], 'progress', 0)
          } else {
            throw new Error((response && response.message) || '上传失败')
          }
        } catch (error) {
          console.error('上传文件失败', error)
          this.$set(this.fileList[fileIndex], 'status', 'error')
          this.$set(this.fileList[fileIndex], 'errorMessage', error.message || '上传失败')
          this.$set(this.fileList[fileIndex], 'progress', 0)
          throw error
        }
      },
  
      // 批量转换文件
      async handleBatchRecognize() {
        const filesToRecognize = this.fileList.filter(f => f.status === 'uploaded' && f.uploadFileId)
        if (filesToRecognize.length === 0) {
          this.$message.warning('没有可转换的文件，请先上传文件')
          return
        }
  
        this.recognizing = true
        
        // 逐个转换，避免并发过多
        for (let i = 0; i < filesToRecognize.length; i++) {
          const file = filesToRecognize[i]
          const fileIndex = this.fileList.findIndex(f => f.uid === file.uid)
          if (fileIndex !== -1) {
            await this.recognizeFile(fileIndex)
            // 每个文件转换间隔500ms
            if (i < filesToRecognize.length - 1) {
              await new Promise(resolve => setTimeout(resolve, 500))
            }
          }
        }
  
        this.recognizing = false
        this.$message.success(`完成 ${filesToRecognize.length} 个文件的转换`)
      },
  
      // 移除转换结果中的文件名
      removeFileNameFromContent(content, fileName) {
        if (!content || !fileName) return content
        
        // 获取文件名（不包含扩展名）
        const nameWithoutExt = fileName.replace(/\.[^/.]+$/, '')
        // 获取完整文件名（包含扩展名）
        const fullFileName = fileName
        
        let result = content
        
        // 移除开头的文件名（可能作为标题或单独一行）
        // 匹配 markdown 标题格式：# 文件名 或 ## 文件名 等
        const titlePattern = new RegExp(`^#{1,6}\\s*${this.escapeRegExp(fullFileName)}\\s*$`, 'm')
        result = result.replace(titlePattern, '')
        
        const titlePattern2 = new RegExp(`^#{1,6}\\s*${this.escapeRegExp(nameWithoutExt)}\\s*$`, 'm')
        result = result.replace(titlePattern2, '')
        
        // 移除单独一行的文件名
        const linePattern = new RegExp(`^${this.escapeRegExp(fullFileName)}\\s*$`, 'm')
        result = result.replace(linePattern, '')
        
        const linePattern2 = new RegExp(`^${this.escapeRegExp(nameWithoutExt)}\\s*$`, 'm')
        result = result.replace(linePattern2, '')
        
        return result.trim()
      },
      
      // 转义正则表达式特殊字符
      escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
      },

      // 转换单个文件
      recognizeFile(index) {
        const file = this.fileList[index]
        if (!file.uploadFileId) {
          this.$message.warning('文件尚未上传，请先上传文件')
          return
        }
  
        if (file.status === 'recognizing') {
          this.$message.warning('文件正在转换中，请稍候')
          return
        }
  
        this.$set(this.fileList[index], 'status', 'recognizing')
        this.$set(this.fileList[index], 'progress', 0)
        this.$set(this.fileList[index], 'errorMessage', null)
  
        // 构建工作流输入
        const inputs = {
          [this.workflowConfig.variableName]: [{
            transfer_method: 'local_file',
            upload_file_id: file.uploadFileId,
            type: 'document'
          }]
        }
  
        let recognizedText = ''
        let isFinished = false
  
        // 调用工作流
        const workflowControl = runWorkflow(
          {
            inputs: inputs,
            user: this.uploadData.userId,
            responseMode: this.workflowConfig.responseMode,
            appName: this.uploadData.appName
          },
          // onMessage
          (message) => {
            // 处理流式响应
            console.log('工作流消息事件:', message.event, message)
            
            if (message.event === 'workflow_started') {
              this.$set(this.fileList[index], 'progress', 10)
            } else if (message.event === 'node_started') {
              this.$set(this.fileList[index], 'progress', 30)
            } else if (message.event === 'node_finished') {
              this.$set(this.fileList[index], 'progress', 60)
              // 尝试从节点输出中提取转换结果
              if (message.data && message.data.outputs) {
                const outputs = message.data.outputs
                // 根据实际工作流输出结构调整
                for (const key in outputs) {
                  if (typeof outputs[key] === 'string') {
                    recognizedText += outputs[key] + '\n'
                  } else if (typeof outputs[key] === 'object' && outputs[key] !== null) {
                    // 如果是对象，尝试提取文本内容
                    if (outputs[key].text) {
                      recognizedText += outputs[key].text + '\n'
                    } else if (outputs[key].content) {
                      recognizedText += outputs[key].content + '\n'
                    } else if (outputs[key].result) {
                      recognizedText += outputs[key].result + '\n'
                    } else if (outputs[key].output) {
                      recognizedText += outputs[key].output + '\n'
                    }
                  }
                }
                // 实时更新转换内容
                if (recognizedText) {
                  // 移除结果中的文件名
                  const cleanedText = this.removeFileNameFromContent(recognizedText, file.name)
                  this.$set(this.fileList[index], 'recognizedContent', cleanedText.trim())
                }
              }
            } else if (message.event === 'workflow_finished') {
              console.log('收到 workflow_finished 事件，开始处理完成逻辑')
              this.$set(this.fileList[index], 'progress', 90)
              isFinished = true
              // 从最终输出中提取转换结果和文件下载URL
              if (message.data && message.data.outputs) {
                const outputs = message.data.outputs
                console.log('工作流完成，输出数据:', outputs)
                
                // 优先从 outputs.result 获取 markdown 结果
                if (outputs.result && typeof outputs.result === 'string') {
                  recognizedText = outputs.result
                  // 移除结果中的文件名
                  recognizedText = this.removeFileNameFromContent(recognizedText, file.name)
                  this.$set(this.fileList[index], 'recognizedContent', recognizedText.trim())
                } else {
                  // 如果没有 result 字段，使用原有逻辑提取文本
                  for (const key in outputs) {
                    if (typeof outputs[key] === 'string') {
                      recognizedText += outputs[key] + '\n'
                    } else if (typeof outputs[key] === 'object' && outputs[key] !== null) {
                      // 如果是对象，尝试提取文本内容
                      if (outputs[key].text) {
                        recognizedText += outputs[key].text + '\n'
                      } else if (outputs[key].content) {
                        recognizedText += outputs[key].content + '\n'
                      } else if (outputs[key].result) {
                        recognizedText += outputs[key].result + '\n'
                      } else if (outputs[key].output) {
                        recognizedText += outputs[key].output + '\n'
                      } else if (Array.isArray(outputs[key])) {
                        // 如果是数组，遍历提取文本
                        outputs[key].forEach(item => {
                          if (typeof item === 'string') {
                            recognizedText += item + '\n'
                          } else if (item && typeof item === 'object') {
                            if (item.text) recognizedText += item.text + '\n'
                            else if (item.content) recognizedText += item.content + '\n'
                          }
                        })
                      } else {
                        // 最后尝试JSON序列化
                        const jsonStr = JSON.stringify(outputs[key], null, 2)
                        if (jsonStr && jsonStr !== '{}' && jsonStr !== '[]') {
                          recognizedText += jsonStr + '\n'
                        }
                      }
                    }
                  }
                  // 立即更新转换内容
                  if (recognizedText) {
                    // 移除结果中的文件名
                    recognizedText = this.removeFileNameFromContent(recognizedText, file.name)
                    this.$set(this.fileList[index], 'recognizedContent', recognizedText.trim())
                  }
                }
                
                // 从 outputs.files 中提取文件下载URL和文件名
                if (outputs.files && Array.isArray(outputs.files) && outputs.files.length > 0) {
                  const fileItem = outputs.files[0]
                  if (fileItem && fileItem.url) {
                    console.log('获取到文件下载URL:', fileItem.url)
                    this.$set(this.fileList[index], 'downloadUrl', fileItem.url)
                  }
                  if (fileItem && fileItem.filename) {
                    console.log('获取到文件下载文件名:', fileItem.filename)
                    this.$set(this.fileList[index], 'downloadFileName', fileItem.filename)
                  }
                }
              }
              
              // 如果 outputs.files 中没有，尝试从 data.files 中获取
              if (message.data && message.data.files && Array.isArray(message.data.files) && message.data.files.length > 0) {
                const fileItem = message.data.files[0]
                if (fileItem && fileItem.url && !this.fileList[index].downloadUrl) {
                  console.log('从 data.files 获取到文件下载URL:', fileItem.url)
                  this.$set(this.fileList[index], 'downloadUrl', fileItem.url)
                }
                if (fileItem && fileItem.filename && !this.fileList[index].downloadFileName) {
                  console.log('从 data.files 获取到文件下载文件名:', fileItem.filename)
                  this.$set(this.fileList[index], 'downloadFileName', fileItem.filename)
                }
              }
              
              console.log('workflow_finished 事件处理完成，转换文本长度:', recognizedText.length)
              // 立即更新状态为已完成，不等待 onEnd 回调
              this.$set(this.fileList[index], 'status', 'recognized')
              this.$set(this.fileList[index], 'progress', 100)
              console.log('文件状态已更新为 recognized')
            } else if (message.event === 'text_chunk' || message.event === 'message') {
              // 处理文本块
              if (message.data) {
                if (message.data.text) {
                  recognizedText += message.data.text
                } else if (message.data.answer) {
                  recognizedText += message.data.answer
                } else if (message.data.content) {
                  recognizedText += message.data.content
                } else if (typeof message.data === 'string') {
                  recognizedText += message.data
                }
                // 实时更新转换内容
                if (recognizedText) {
                  // 移除结果中的文件名
                  const cleanedText = this.removeFileNameFromContent(recognizedText, file.name)
                  this.$set(this.fileList[index], 'recognizedContent', cleanedText.trim())
                }
              }
            } else if (message.event === 'error') {
              // 处理错误事件
              console.error('工作流错误:', message.data || message.message)
            }
          },
          // onEnd
          () => {
            console.log('onEnd 回调被调用，文件:', file.name, '转换文本长度:', recognizedText.length)
            // 确保状态更新
            this.$set(this.fileList[index], 'status', 'recognized')
            // 如果还没有转换内容，使用已提取的内容或默认文本
            let finalContent = recognizedText.trim() || '转换完成，但未获取到内容'
            // 移除结果中的文件名
            if (finalContent && finalContent !== '转换完成，但未获取到内容') {
              finalContent = this.removeFileNameFromContent(finalContent, file.name)
            }
            this.$set(this.fileList[index], 'recognizedContent', finalContent.trim())
            this.$set(this.fileList[index], 'progress', 100)
            
            console.log('文件状态已更新为 recognized，内容:', finalContent.substring(0, 50) + '...')
            
            if (!recognizedText.trim()) {
              this.$message.warning(`文件 ${file.name} 转换完成，但未获取到转换内容`)
            } else {
              this.$message.success(`文件 ${file.name} 转换完成`)
            }
          },
          // onError
          (error) => {
            console.error('转换文件失败', error)
            this.$set(this.fileList[index], 'status', 'error')
            this.$set(this.fileList[index], 'errorMessage', error.message || '转换失败')
            this.$set(this.fileList[index], 'progress', 0)
            this.$message.error(`文件 ${file.name} 转换失败: ${error.message || '未知错误'}`)
          }
        )
  
        // 保存workflow控制对象，以便可以取消
        this.$set(this.fileList[index], 'workflowControl', workflowControl)
      },
  
      // 选择文件
      selectFile(index) {
        this.selectedFileIndex = index
        const file = this.fileList[index]
        // 自动滚动到对比区域
        this.$nextTick(() => {
          const comparisonSection = document.querySelector('.comparison-section')
          if (comparisonSection) {
            comparisonSection.scrollIntoView({ behavior: 'smooth', block: 'start' })
          }
        })
      },
  
      // 查看对比
      viewComparison(index) {
        this.selectedFileIndex = index
        // 滚动到对比区域
        this.$nextTick(() => {
          const comparisonSection = document.querySelector('.comparison-section')
          if (comparisonSection) {
            comparisonSection.scrollIntoView({ behavior: 'smooth', block: 'start' })
          }
        })
      },
  
      // 关闭对比
      closeComparison() {
        this.selectedFileIndex = -1
      },
  
      // 获取状态文本
      getStatusText(status) {
        const statusMap = {
          'ready': '待上传',
          'uploading': '上传中',
          'uploaded': '已上传',
          'recognizing': '转换中',
          'recognized': '已转换',
          'error': '错误'
        }
        return statusMap[status] || '未知'
      },
  
      // 格式化文件大小
      formatFileSize(bytes) {
        if (!bytes) return '0 B'
        const k = 1024
        const sizes = ['B', 'KB', 'MB', 'GB']
        const i = Math.floor(Math.log(bytes) / Math.log(k))
        return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
      },
  
      // 主题切换
      toggleTheme() {
        // 主题切换逻辑
        document.body.classList.toggle('dark-theme')
      },
  
      // 登录处理
      handleLogin() {
        // 登录逻辑
        this.$router.push('/login')
      },

      // 复制转换内容
      copyRecognizedContent() {
        if (this.selectedFile && this.selectedFile.recognizedContent) {
          const textarea = document.createElement('textarea')
          textarea.value = this.selectedFile.recognizedContent
          document.body.appendChild(textarea)
          textarea.select()
          try {
            document.execCommand('copy')
            this.$message.success('转换内容已复制到剪贴板')
          } catch (err) {
            this.$message.error('复制失败，请手动复制')
          }
          document.body.removeChild(textarea)
        }
      },

      // 下载原文件
      downloadOriginalFile() {
        if (this.selectedFile && this.selectedFile.raw) {
          const url = URL.createObjectURL(this.selectedFile.raw)
          const a = document.createElement('a')
          a.href = url
          a.download = this.selectedFile.name
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)
          URL.revokeObjectURL(url)
        } else if (this.selectedFile && this.selectedFile.originalUrl) {
          // 如果是URL，直接打开新窗口下载
          window.open(this.selectedFile.originalUrl, '_blank')
        }
      },

      // 下载转换结果文件
      downloadRecognizedFile() {
        if (this.selectedFile && this.selectedFile.downloadUrl) {
          // 使用 fetch 下载文件，以便指定文件名
          fetch(this.selectedFile.downloadUrl)
            .then(response => response.blob())
            .then(blob => {
              // 创建下载链接
              const url = URL.createObjectURL(blob)
              const a = document.createElement('a')
              a.href = url
              // 使用响应中的文件名，如果没有则使用默认名称
              a.download = this.selectedFile.downloadFileName || '转换结果文件'
              document.body.appendChild(a)
              a.click()
              document.body.removeChild(a)
              URL.revokeObjectURL(url)
              this.$message.success('开始下载转换结果文件')
            })
            .catch(error => {
              console.error('下载文件失败:', error)
              // 如果 fetch 失败，回退到直接打开URL
              window.open(this.selectedFile.downloadUrl, '_blank')
              this.$message.success('开始下载转换结果文件')
            })
        } else {
          this.$message.warning('未找到可下载的文件')
        }
      }
    }
  }
  </script>
  
  <style scoped lang="scss">
  .pdf-recognition-page {
    min-height: 100vh;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    padding-bottom: 40px;

  .page-container {
    max-width: 100%;
    margin: 0 auto;
    padding: 80px 20px 20px 20px; /* 增加顶部内边距，防止被导航栏挡住 */
  }
  
  .page-header {
    text-align: center;
    color: #333;
    margin-bottom: 20px;
    padding-top: 0;
    padding-bottom: 15px;
    border-bottom: 1px solid #e0e0e0;
  
    .page-title {
      font-size: 20px;
      font-weight: 600;
      margin: 0 0 8px 0;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #333;
  
      i {
        font-size: 24px;
        margin-right: 8px;
        color: #409eff;
      }
      
      i:last-child {
        margin-right: 0;
      }
    }
  
    .page-subtitle {
      font-size: 13px;
      color: #666;
      margin: 0;
    }
  }

  // 主内容区域：左右分栏布局
  .main-content {
    display: flex;
    height: calc(100vh - 100px);
    min-height: 600px;
    
    > * {
      margin-right: 20px;
    }
    
    > *:last-child {
      margin-right: 0;
    }
  }

  // 左侧：文件列表区域
  .left-panel {
    width: 350px;
    min-width: 300px;
    background: white;
    border-radius: 12px;
    padding: 20px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
    display: flex;
    flex-direction: column;
    overflow: hidden;

    .action-buttons {
      display: flex;
      flex-direction: column;
      margin-bottom: 15px;

      .el-button {
        width: 100%;
        margin-bottom: 10px;
        margin-left: 0;
      }
      
      .el-button:last-child {
        margin-bottom: 0;
      }
      
      .el-button:nth-child(2) {
        margin-left: 0;
      }
    }

    .upload-options {
      margin-bottom: 15px;
      padding-bottom: 15px;
      border-bottom: 1px solid #e0e0e0;
    }

    .section-stats {
      display: flex;
      flex-wrap: wrap;
      margin-bottom: 15px;
      padding-bottom: 15px;
      border-bottom: 1px solid #e0e0e0;
      margin-right: -10px;

      .stat-item {
        display: flex;
        align-items: center;
        color: #666;
        font-size: 12px;
        padding: 4px 8px;
        background-color: #f5f5f5;
        border-radius: 4px;
        margin-right: 10px;
        margin-bottom: 10px;

        i {
          font-size: 14px;
          margin-right: 5px;
        }
        
        i:last-child {
          margin-right: 0;
        }
      }
    }

    .files-list {
      flex: 1;
      overflow-y: auto;
      overflow-x: hidden;
      .file-item {
        display: flex;
        align-items: flex-start;
        padding: 12px;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        margin-bottom: 8px;
        cursor: pointer;
        transition: all 0.3s;

        &:hover {
          background-color: #f5f5f5;
          border-color: #409eff;
        }

        &.active {
          background-color: #ecf5ff;
          border-color: #409eff;
        }

        &.uploaded {
          border-left: 4px solid #67c23a;
        }

        &.recognizing {
          border-left: 4px solid #409eff;
        }

        &.recognized {
          border-left: 4px solid #67c23a;
        }

        &.error {
          border-left: 4px solid #f56c6c;
        }

        .file-icon {
          width: 32px;
          height: 32px;
          display: flex;
          align-items: center;
          justify-content: center;
          margin-right: 10px;
          flex-shrink: 0;
          color: #409eff;

          i {
            font-size: 20px;
          }
        }

        .file-info {
          flex: 1;
          min-width: 0;
          overflow: hidden;

          .file-name {
            font-size: 14px;
            font-weight: 500;
            color: #333;
            margin-bottom: 5px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }

          .file-meta {
            display: flex;
            align-items: center;
            font-size: 12px;
            color: #999;

            > * {
              margin-right: 15px;
            }
            
            > *:last-child {
              margin-right: 0;
            }

            .file-size {
              color: #666;
            }

            .file-status {
              padding: 2px 8px;
              border-radius: 4px;
              font-size: 12px;

              &.ready {
                background-color: #f0f0f0;
                color: #666;
              }

              &.uploading {
                background-color: #e6f7ff;
                color: #409eff;
              }

              &.uploaded {
                background-color: #f0f9ff;
                color: #67c23a;
              }

              &.recognizing {
                background-color: #e6f7ff;
                color: #409eff;
              }

              &.recognized {
                background-color: #f0f9ff;
                color: #67c23a;
              }

              &.error {
                background-color: #fef0f0;
                color: #f56c6c;
              }
            }
          }

          .file-progress {
            margin-top: 8px;
          }

          .file-error {
            margin-top: 8px;
            color: #f56c6c;
            font-size: 12px;
            display: flex;
            align-items: center;

            i {
              margin-right: 5px;
            }
          }
        }

        .file-actions {
          display: flex;
          flex-shrink: 0;
          margin-left: 5px;

          .el-button {
            margin-right: 5px;
          }
          
          .el-button:last-child {
            margin-right: 0;
          }
        }
      }

      .empty-state {
        text-align: center;
        padding: 40px 20px;
        color: #999;

        i {
          font-size: 36px;
          margin-bottom: 10px;
          display: block;
        }

        p {
          font-size: 13px;
          margin: 0;
        }
      }
    }
  }

  // 右侧：对比区域
  .right-panel {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;

    .comparison-section {
      flex: 1;
      background: white;
      border-radius: 12px;
      padding: 20px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    .no-selection {
      flex: 1;
      background: white;
      border-radius: 12px;
      padding: 20px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #999;

      i {
        font-size: 64px;
        margin-bottom: 20px;
        opacity: 0.5;
      }

      p {
        font-size: 16px;
        margin: 0;
      }
    }
  }

  // 对比区域样式（在 right-panel 内部）
  .comparison-section {
    .section-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 0px;

      .section-title {
        font-size: 20px;
        font-weight: 600;
        color: #333;
        display: flex;
        align-items: center;
        margin: 0;

        i {
          font-size: 24px;
          margin-right: 10px;
        }
        
        i:last-child {
          margin-right: 0;
        }
      }
    }

    .comparison-container {
      flex: 1;
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 20px;
      min-height: 0;
      overflow: hidden;

      .comparison-panel {
        display: flex;
        flex-direction: column;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        overflow: hidden;

        .panel-header {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 0px 20px;
          background-color: #f5f5f5;
          border-bottom: 1px solid #e0e0e0;

          span {
            font-size: 16px;
            font-weight: 500;
            color: #333;
            display: flex;
            align-items: center;

            i {
              font-size: 18px;
              margin-right: 8px;
            }
            
            i:last-child {
              margin-right: 0;
            }
          }
          
          .panel-actions {
            display: flex;
            align-items: center;
            
            .el-button {
              margin-left: 10px;
            }
            
            .el-button:first-child {
              margin-left: 0;
            }
          }
        }

        .panel-content {
          flex: 1;
          overflow: auto;
          padding: 20px;

          .pdf-viewer {
            width: 100%;
            height: 100%;
            min-height: 400px;
          }

          .recognized-content {
            height: 100%;

            .recognized-text {
              margin: 0;
              padding: 0;
              font-size: 14px;
              line-height: 1.6;
              color: #333;
              word-wrap: break-word;
              
              // Markdown 样式
              h1, h2, h3, h4, h5, h6 {
                margin-top: 1em;
                margin-bottom: 0.5em;
                font-weight: 600;
                line-height: 1.25;
              }
              
              h1 {
                font-size: 2em;
                border-bottom: 1px solid #eaecef;
                padding-bottom: 0.3em;
              }
              
              h2 {
                font-size: 1.5em;
                border-bottom: 1px solid #eaecef;
                padding-bottom: 0.3em;
              }
              
              h3 {
                font-size: 1.25em;
              }
              
              p {
                margin: 0 0 1em 0;
              }
              
              ul, ol {
                margin: 0 0 1em 0;
                padding-left: 2em;
              }
              
              li {
                margin: 0.25em 0;
              }
              
              code {
                padding: 0.2em 0.4em;
                margin: 0;
                font-size: 85%;
                background-color: rgba(27, 31, 35, 0.05);
                border-radius: 3px;
                font-family: 'Courier New', monospace;
              }
              
              pre {
                padding: 16px;
                overflow: auto;
                font-size: 85%;
                line-height: 1.45;
                background-color: #f6f8fa;
                border-radius: 6px;
                margin: 0 0 1em 0;
                
                code {
                  display: inline;
                  padding: 0;
                  margin: 0;
                  overflow: visible;
                  line-height: inherit;
                  word-wrap: normal;
                  background-color: transparent;
                  border: 0;
                }
              }
              
              blockquote {
                padding: 0 1em;
                color: #6a737d;
                border-left: 0.25em solid #dfe2e5;
                margin: 0 0 1em 0;
              }
              
              table {
                border-collapse: collapse;
                margin: 0 0 1em 0;
                width: 100%;
                
                th, td {
                  padding: 6px 13px;
                  border: 1px solid #dfe2e5;
                }
                
                th {
                  font-weight: 600;
                  background-color: #f6f8fa;
                }
              }
              
              a {
                color: #0366d6;
                text-decoration: none;
                
                &:hover {
                  text-decoration: underline;
                }
              }
              
              img {
                max-width: 100%;
                height: auto;
              }
            }
          }

          .no-preview,
          .no-content {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100%;
            color: #999;

            i {
              font-size: 48px;
              margin-bottom: 15px;
            }

            p {
              font-size: 14px;
              margin: 0 0 15px 0;
            }
          }
        }
      }

      .original-panel {
        .panel-header {
          background-color: #e6f7ff;
        }
      }

      .recognized-panel {
        .panel-header {
          background-color: #f0f9ff;
        }
      }
    }
  }

  @media (max-width: 1200px) {
    .main-content {
      flex-direction: column;
      height: auto;
    }

    .left-panel {
      width: 100%;
      
    }

    .comparison-container {
      grid-template-columns: 1fr;
      min-height: 500px;

      .comparison-panel {
        min-height: 400px;
      }
    }
  }
  }
  </style>